package hello

import (
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"os"
	"reflect"

	"github.com/gin-gonic/gin"
	"github.com/jmespath/go-jmespath"
)

func Struct2map(configStrut any) (data map[string]any, err error) {
	// 通过反射将结构体转换成map
	data = make(map[string]any)
	objT := reflect.TypeOf(configStrut)
	objV := reflect.ValueOf(configStrut)
	for i := 0; i < objT.NumField(); i++ {
		fileName, ok := objT.Field(i).Tag.Lookup("json")
		if ok {
			data[fileName] = objV.Field(i).Interface()
		} else {
			data[objT.Field(i).Name] = objV.Field(i).Interface()
		}
	}
	return data, nil
}

func GetJsonData() []byte {
	data, err := os.ReadFile("./hello/config.json")
	if err != nil {
		fmt.Println("readfile error")
	}
	return data
}

func ParseJson2Struct() *AutoGenerated {
	datafig, err := os.ReadFile("./hello/config.json")
	if err != nil {
		fmt.Println("ParseJson: os.ReadFile.....")
	}
	cfg := new(AutoGenerated)
	err = json.Unmarshal(datafig, cfg)
	if err != nil {
		fmt.Println("ParseJson: json.Unmarshal.....")
	}
	return cfg
}

func GetConfigStruct() *AutoGenerated {
	//fmt.Println(*ParseJson2Struct())
	return ParseJson2Struct()
}

func GetAllConfigData(context *gin.Context) {
	context.JSON(http.StatusOK, GetConfigStruct())
}

func getServerVersion(context *gin.Context) {

	context.JSON(http.StatusOK, GetConfigStruct().ServerVersion)
}

func getOneClassInfo(context *gin.Context, postJsondata []byte) {
	jsonData := GetJsonData()
	var totalData interface{}
	err := json.Unmarshal(jsonData, &totalData)
	if err != nil {
		fmt.Println("getServerInfo:111json.Unmarshal")
	}

	var jsonMap map[string]interface{}
	err = json.Unmarshal(postJsondata, &jsonMap)
	if err != nil {
		fmt.Println("getServerInfo:222json.Unmarshal")
	}

	path := getKeys(jsonMap)
	res, err := jmespath.Search(path, totalData)
	if err != nil {
		fmt.Println("jmespath Search failed....")
	}
	context.JSON(http.StatusOK, res)
}

func getServerInfo(context *gin.Context, postJsondata []byte) {
	getOneClassInfo(context, postJsondata)
}

func getClientInfo(context *gin.Context, postJsondata []byte) {
	getOneClassInfo(context, postJsondata)
}

func getMicroConferenceInfo(context *gin.Context, postJsondata []byte) {
	getOneClassInfo(context, postJsondata)
}

func getH5ServerInfo(context *gin.Context) {
	context.JSON(http.StatusOK, GetConfigStruct().H5Server)
}

func getCallRecordServicesInfo(context *gin.Context, postJsondata []byte) {
	getOneClassInfo(context, postJsondata)
}

func getShareMeetingInfo(context *gin.Context, postJsondata []byte) {
	getOneClassInfo(context, postJsondata)
}
func getConferenceInfo(context *gin.Context, postJsondata []byte) {
	getOneClassInfo(context, postJsondata)
}

func getLvsInfo(context *gin.Context, postJsondata []byte) {
	getOneClassInfo(context, postJsondata)
}

func getExtendServerInfo(context *gin.Context, postJsondata []byte) {
	getOneClassInfo(context, postJsondata)
}

func getSyncServicesInfo(context *gin.Context, postJsondata []byte) {
	getOneClassInfo(context, postJsondata)
}

func getAgentInfo(context *gin.Context, postJsondata []byte) {
	getOneClassInfo(context, postJsondata)
}
func getDiversionInfo(context *gin.Context, postJsondata []byte) {
	getOneClassInfo(context, postJsondata)
}
func getDdioServerInfo(context *gin.Context, postJsondata []byte) {
	getOneClassInfo(context, postJsondata)
}
func getForceUpdateInfo(context *gin.Context, postJsondata []byte) {
	getOneClassInfo(context, postJsondata)
}
func getDataserverInfo(context *gin.Context, postJsondata []byte) {
	getOneClassInfo(context, postJsondata)
}
func getVersionMarkInfo(context *gin.Context, postJsondata []byte) {
	getOneClassInfo(context, postJsondata)
}
func getVersionExplainInfo(context *gin.Context, postJsondata []byte) {
	getOneClassInfo(context, postJsondata)
}
func getRouterInfo(context *gin.Context, postJsondata []byte) {
	getOneClassInfo(context, postJsondata)
}

func getKeys(data map[string]interface{}) string {
	var j int
	var flag int
	var keyList []string
	//fmt.Println(len(data))
	for j = 0; j < 20; j++ {
		flag = 0
		for k, v := range data {
			keyList = append(keyList, k)
			switch value := v.(type) {
			case string, int, float64, uint:
				flag = -1
			case map[string]interface{}:
				data = value
				fmt.Println(data)
			}
		}
		if flag == -1 {
			break
		}
	}
	queryString := keyList[0]
	var i int
	if len(keyList) > 1 {
		queryString += "."
		for i = 1; i < len(keyList)-1; i++ {
			queryString += keyList[i]
			queryString += "."
		}
		queryString += keyList[i]
	}
	return queryString
}

// func judgeKeys(data map[string]interface{}) string {
// 	var j int
// 	var flag int
// 	var keyList []string
// 	//fmt.Println(len(data))
// 	for j = 0; j < 20; j++ {
// 		flag = 0
// 		for k, v := range data {
// 			keyList = append(keyList, k)
// 			switch value := v.(type) {
// 			case string, int, float64, uint:
// 				flag = -1
// 			case map[string]interface{}:
// 				data = value
// 				fmt.Println(data)
// 			}
// 		}
// 		if flag == -1 {
// 			break
// 		}
// 	}
// 	queryString := keyList[0]
// 	var i int
// 	if len(keyList) > 1 {
// 		queryString += "."
// 		for i = 1; i < len(keyList)-1; i++ {
// 			queryString += keyList[i]
// 			queryString += "."
// 		}
// 		queryString += keyList[i]
// 	}
// 	return queryString
// }

func GetConfigInfo(context *gin.Context) {
	data, _ := io.ReadAll(context.Request.Body)
	var res map[string]interface{}
	err := json.Unmarshal(data, &res)
	if err != nil {
		fmt.Println("GetConfigInfo: json.Unmarshal failed...")
	}

	for k, v := range res {
		switch v.(type) {
		case string, int, float64:
			switch k {
			case "serverVersion":
				getServerVersion(context)
			case "h5Server":
				getH5ServerInfo(context)
			}
		case map[string]interface{}:
			switch k {
			case "server":
				getServerInfo(context, data)
			case "client":
				getClientInfo(context, data)
			case "microConference":
				getMicroConferenceInfo(context, data)
			case "callRecordServices":
				getCallRecordServicesInfo(context, data)
			case "shareMeeting":
				getShareMeetingInfo(context, data)
			case "conference":
				getConferenceInfo(context, data)
			case "lvs":
				getLvsInfo(context, data)
			case "extendServer":
				getExtendServerInfo(context, data)
			case "syncServices":
				getSyncServicesInfo(context, data)
			case "agent":
				getAgentInfo(context, data)
			case "diversion":
				getDiversionInfo(context, data)
			case "ddioServer":
				getDdioServerInfo(context, data)
			case "forceUpdate":
				getForceUpdateInfo(context, data)
			case "dataserver":
				getDataserverInfo(context, data)
			case "versionMark":
				getVersionMarkInfo(context, data)
			case "versionExplain":
				getVersionExplainInfo(context, data)
			case "router":
				getRouterInfo(context, data)
			}
		}
	}
}

func SetConfigInfo(context *gin.Context, modle string) (int, string) {
	var code int = -1
	var errorMessage string
	raw := GetJsonData()
	var configStruct AutoGenerated
	err := json.Unmarshal(raw, &configStruct)
	if err != nil {
		fmt.Println("SetConfigInfo: json.Unmarshal failed")
	}
	data, _ := io.ReadAll(context.Request.Body)
	var res map[string]interface{}
	err = json.Unmarshal(data, &res)
	if err != nil {
		fmt.Println("GetConfigInfo: json.Unmarshal failed...")
	}

	for k := range res {
		if k != modle {
			errorMessage = "Only the config of " + modle + " can be modified here"
			return code, errorMessage
		}
	}

	err = json.Unmarshal(data, &configStruct)
	if err != nil {
		Logger("Error", "json Unmarshal failed")
		errorMessage = "type of value is wrong"
		return code, errorMessage
	}

	Indata, err := json.MarshalIndent(configStruct, "", "  ")
	if err != nil {
		fmt.Println("json.MarshalIndent failed")
	}

	fp, err := os.Create("./newConfig.json")
	if err != nil {
		fmt.Println("os.Create fail...")
	}
	defer fp.Close()

	fp.Write(Indata)

	code = 0
	errorMessage = "modify success!!!"
	return code, errorMessage
}
